Pointerova aritmetika

Otázka od: Zdenek Moravec

10. 12. 2002 15:51

Zdravim vsechny,

pokud je napr. pWords: pointer a pomoci getmem (pWords, 1000 * sizeof
(someRecord)) vyalokuji buffer pro tisic recordu, jak se potom dostanu napr.
na 70. z nich ?

Ja pouzivam konstrukci pWord = Ptr (longint (Addr (pWords^)) + (70-1) *
sizeof (someRecord)). Ma nekdo lepsi napad ? Pripadne napad jak usporne
vyuzivat pamet k ulozeni dat bez zbytecne rezie, kterou prinasi ruzne TListy
a TCollectiony apod. a s moznosti najednou nacist nebo zapsat celou tuto
mnozinu recordu prikazem BlockRead resp. Blockwrite do souboru ?

S pozdravem (Regards)
Zdenek Moravec moravec@digitech.cz

Odpovedá: Delphin

10. 12. 2002 15:59

Zkus to takto, vysledek bude stejne rychly, ale pocitat bude za tebe
prekladac.

type TRec=record
                    x:integer;
                  end;
PRecords=^TRecords;
TRecords=array [0..100] of TRec;

var Records:PRecords;
begin
 getmem(Records,1000*sizeof(TRec));

 Records^[70].x:=1;


----- Original Message -----
From: "Zdenek Moravec" <zmo@volny.cz>
To: "Konference Delphi" <delphi-l@clexpert.cz>
Sent: Tuesday, December 10, 2002 2:54 PM
Subject: Pointerova aritmetika


> Zdravim vsechny,
>
> pokud je napr. pWords: pointer a pomoci getmem (pWords, 1000 * sizeof
> (someRecord)) vyalokuji buffer pro tisic recordu, jak se potom dostanu
napr.
> na 70. z nich ?
>
> Ja pouzivam konstrukci pWord = Ptr (longint (Addr (pWords^)) + (70-1) *
> sizeof (someRecord)). Ma nekdo lepsi napad ? Pripadne napad jak usporne
> vyuzivat pamet k ulozeni dat bez zbytecne rezie, kterou prinasi ruzne
TListy
> a TCollectiony apod. a s moznosti najednou nacist nebo zapsat celou tuto
> mnozinu recordu prikazem BlockRead resp. Blockwrite do souboru ?
>
> S pozdravem (Regards)
> Zdenek Moravec moravec@digitech.cz
>
>
>
>

Odpovedá: Tom xXx

10. 12. 2002 16:11



 Coz takhle pouzit stary dobry Pascal se vsim vsudy???

type
   tWords = array [1 .. 1000] of Word;
   pWords = ^tWords;
var
   MyWords:pWords;
begin
.....
   new(Mywords);
   MyWords[70] := 1234;

   //Uz nepotrebuji
   dispose(MyWords);
end;

 Pro pripad tech souboru, nebylo by dobre pouzit mapovani do pameti????

T.

Odpovedá: Tom xXx

10. 12. 2002 16:06


Sorry, zapomnel jsem na zobacek  

   MyWords^[70] := 1234;

T.

Odpovedá: Zdenek Moravec

10. 12. 2002 15:55

Dekuji za pomoc, je to opravdu velmi efektivni - funguje dokonce i array
[0..0] of TRec.

S pozdravem (Regards)
Zdenek Moravec zmo@volny.cz

> Zkus to takto, vysledek bude stejne rychly, ale pocitat bude za tebe
> prekladac.
>
> type TRec=record
> x:integer;
> end;
> PRecords=^TRecords;
> TRecords=array [0..100] of TRec;
>
> var Records:PRecords;
> begin
> getmem(Records,1000*sizeof(TRec));
>
> Records^[70].x:=1;
>


Odpovedá: Ondrej Kelle

10. 12. 2002 16:18

> pokud je napr. pWords: pointer a pomoci getmem (pWords,
> 1000 * sizeof(someRecord)) vyalokuji buffer pro tisic recordu,
> jak se potom dostanu napr. na 70. z nich ?
>
> Ja pouzivam konstrukci pWord = Ptr (longint (Addr (pWords^))
> + (70-1) * sizeof (someRecord)). Ma nekdo lepsi napad ?

Napadaju ma dva sposoby, mozes pouzit pointer aritmetics alebo array
typecast, napriklad:

type
  PMyRecord = ^TMyRecord;
  TMyRecord = record
    MyInt: Integer;
    MyStr: array[0..255] of Char;
  end;
  TMyRecords = array[0..0] of TMyRecord;

const
  Count = 20;
var
  Buf: Pointer;
  P: PMyRecord;
  I: Integer;
begin
  Buf := AllocMem(Count * SizeOf(TMyRecord));
  try
    // fill in some data...
    P := Buf;
    for I := 0 to Count - 1 do
    begin
      with P^ do
      begin
        MyInt := I;
        StrLCopy(MyStr, PChar(IntToStr(I)), SizeOf(MyStr) - 1);
      end;
      Inc(P);
    end;

    // iterate using pointer arithmetics
    P := Buf;
    for I := 0 to Count - 1 do
    begin
      with P^ do
        
OutputDebugString(PChar(Format('record %d: MyInt = %d, MyStr =
''%s''', [I,
MyInt, MyStr])));
      Inc(P);
    end;

    // iterate using array typecast
    for I := 0 to Count - 1 do
      with TMyRecords(Buf^)[I] do
        
OutputDebugString(PChar(Format('record %d: MyInt = %d, MyStr =
''%s''', [I,
MyInt, MyStr])));
  finally
    FreeMem(Buf);
  end;
end;

> Pripadne napad jak usporne vyuzivat pamet k ulozeni dat
> bez zbytecne rezie, kterou prinasi ruzne TListy a TCollectiony
> apod.

TList ma podla mna zanedbatelnu reziu, hlavne ak si vopred nastavis
Capacity, pritom kod s jeho pouzitim byva o nieco citatelnejsi.

> a s moznosti najednou nacist nebo zapsat celou tuto
> mnozinu recordu prikazem BlockRead resp. Blockwrite
> do souboru ?

Na to potrebujes mat suvisly blok dat, takze v tom pripade TList odpada.
Mozno by sa Ti hodil nejaky objekt, ktory bude vnutorne pouzivat
TMemoryStream. V nom mas vlastnost Memory, ku ktorej mozes pristupovat
horeuvedenym sposobom, ale ma tiez sikovnu metodu SaveToFile  

HTH
TOndrej

Odpovedá: Petr Vones

10. 12. 2002 18:48

From: "Zdenek Moravec" <zmo@volny.cz>
> Ja pouzivam konstrukci pWord = Ptr (longint (Addr (pWords^)) + (70-1) *
> sizeof (someRecord)). Ma nekdo lepsi napad ? Pripadne napad jak usporne
> vyuzivat pamet k ulozeni dat bez zbytecne rezie, kterou prinasi ruzne TListy
> a TCollectiony apod. a s moznosti najednou nacist nebo zapsat celou tuto
> mnozinu recordu prikazem BlockRead resp. Blockwrite do souboru ?

Dynamicka pole

Petr Vones